package com.sky.service.impl;

import com.alibaba.fastjson.JSON;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.sky.constant.MessageConstant;
import com.sky.context.BaseContext;
import com.sky.dto.*;
import com.sky.entity.AddressBook;
import com.sky.entity.OrderDetail;
import com.sky.entity.Orders;
import com.sky.entity.ShoppingCart;
import com.sky.exception.AddressBookBusinessException;
import com.sky.exception.OrderBusinessException;
import com.sky.exception.ShoppingCartBusinessException;
import com.sky.mapper.*;
import com.sky.result.PageResult;
import com.sky.service.OrderService;
import com.sky.utils.WeChatPayUtil;
import com.sky.vo.OrderStatisticsVO;
import com.sky.vo.OrderSubmitVO;
import com.sky.vo.OrderVO;
import com.sky.webSocket.webSocketServer;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

@Service
@Slf4j
public class OrderServiceImpl implements OrderService {
    @Autowired
    private OrderMapper orderMapper;
    @Autowired
    private OrderDetailMapper  orderDetailMapper;
    @Autowired
    private AddressBookMapper addressBookMapper;
    @Autowired
    private ShoppingCartMapper shoppingCartMapper;
    @Autowired
    private WeChatPayUtil weChatPayUtil;
    @Autowired
    private webSocketServer webSocketServer;

    @Override
    public OrderStatisticsVO statistics() {
        //查询所有的订单的数据，然后进行判断订单的状态，如果是待派送,（已接单，未接单），confirmed数量加1，如果是派送中数量，deliveryInProgress数量加1，如果是待接单，toBeConfirmed数量+1
        //第一种方式：获取所有的订单，然后进行判断订单的状态（缺点：订单的数量很多时，性能差）
        //第二种方式：根据订单的状态进行查询数据库，然后进行赋值（有点：性能好），只需要查询不同订单状态的订单数。
        List<Orders> ordersList = orderMapper.queryOrderList();
        //初始化数据
        OrderStatisticsVO orderStatisticsVO = new OrderStatisticsVO();
        orderStatisticsVO.setConfirmed(0);
        orderStatisticsVO.setDeliveryInProgress(0);
        orderStatisticsVO.setToBeConfirmed(0);
        //遍历订单
        for (Orders orders : ordersList){
            //状态：待派送（已接单3）
            if(orders.getStatus() == Orders.CONFIRMED){
                orderStatisticsVO.setConfirmed(orderStatisticsVO.getConfirmed() + 1);
            }
            //状态：派送中4
            else if(orders.getStatus() == Orders.DELIVERY_IN_PROGRESS){
                orderStatisticsVO.setDeliveryInProgress(orderStatisticsVO.getDeliveryInProgress() + 1);
            }
            //状态：待接单2
            else if(orders.getStatus() == Orders.REFUND){
                orderStatisticsVO.setToBeConfirmed(orderStatisticsVO.getToBeConfirmed() + 1);
            }
        }
        return orderStatisticsVO;
    }

    @Override
    @Transactional
    public OrderSubmitVO submitOrder(OrdersSubmitDTO ordersSubmitDTO) {
        //第一步：根据传递过来的地址id查询地址信息，看地址信息是否存在；如果不存在则抛出异常
        Long addressBookId = ordersSubmitDTO.getAddressBookId();
        AddressBook addressBook = addressBookMapper.getAddressById(addressBookId);
        if(addressBook == null){
            throw new AddressBookBusinessException(MessageConstant.ADDRESS_BOOK_IS_NULL);
        }
        //第二步：查看该用户的购物车数据，如果购物车中没有数据，则进行抛出异常
        Long userId = BaseContext.getCurrentId();
        List<ShoppingCart> shoppingCartList = shoppingCartMapper.queryList(userId);
        if(shoppingCartList == null || shoppingCartList.size() == 0){
            throw new ShoppingCartBusinessException(MessageConstant.SHOPPING_CART_IS_NULL);
        }
        //第三步：根据传递过来的数据项order数据表中插入一条订单的数据
        Orders orders = new Orders();
        BeanUtils.copyProperties(ordersSubmitDTO,orders);
        //使用系统自带的时间戳来进行赋值
        orders.setNumber(String.valueOf(System.currentTimeMillis()));
        orders.setStatus(Orders.PENDING_PAYMENT);
        orders.setUserId(userId);
        orders.setOrderTime(LocalDateTime.now());
        orders.setPayStatus(Orders.UN_PAID);
        orders.setPhone(addressBook.getPhone());
        orders.setAddress(addressBook.getDetail());
        orders.setConsignee(addressBook.getConsignee());
        orderMapper.insertOrder(orders);
        //第四步：将获取到的购物车中商品的信息插入order_detail表中，批量插入
        //使用返回的订单id进行批量插入
        List<OrderDetail> orderDetailList = new ArrayList<>();
        //先将购物车的数据进行拷贝，在加入orderId的数据
       for (ShoppingCart shoppingCart : shoppingCartList) {
           OrderDetail orderDetail = new OrderDetail();
           BeanUtils.copyProperties(shoppingCart,orderDetail);
           orderDetail.setOrderId(orders.getId());
           orderDetailList.add(orderDetail);
       }
        orderDetailMapper.insertBatch(orderDetailList);
        //第五步：删除当前用户的购物车的商品的数据
        shoppingCartMapper.deleteByUserId(userId);
        //第六步：将获取到的订单数据进行封装，传递给Controller层
        OrderSubmitVO orderSubmitVO = OrderSubmitVO.builder()
                .id(orders.getId())
                .orderAmount(orders.getAmount())
                .orderNumber(orders.getNumber())
                .orderTime(orders.getOrderTime())
                .build();
        return orderSubmitVO;
    }

    @Override
    public void paySuccess(String number) {
        orderMapper.updateStatus(number,Orders.PAID);
    }

    @Override
    public PageResult queryHistoryOrders(Integer page, Integer pageSize, Integer status) {
        // 1. 分页查询订单列表
        Long userId = BaseContext.getCurrentId();
        OrdersPageQueryDTO queryDTO = new OrdersPageQueryDTO();
        queryDTO.setUserId(userId);
        queryDTO.setStatus(status);

        PageHelper.startPage(page, pageSize);
        List<Orders> ordersList = orderMapper.queryList(queryDTO);
        PageInfo<Orders> pageInfo = new PageInfo<>(ordersList);

        // 2. 无数据时直接返回
        if (ordersList.isEmpty()) {
            return new PageResult(pageInfo.getTotal(), Collections.emptyList());
        }

        // 3. 获取所有订单的id列表
        List<Long> orderIds = ordersList.stream()
                .map(Orders::getId)
                .collect(Collectors.toList());

        //4.根据订单的Id进行批量查询
        List<OrderDetail> details = orderDetailMapper.queryBatch(orderIds); // 方法名修正为 queryByOrderIds
        //5.将查询到的订单详情的数据根据订单id进行分组
        Map<Long, List<OrderDetail>> detailsMap = details.stream()
                .collect(Collectors.groupingBy(OrderDetail::getOrderId));

        // 4. 组装VO列表
        List<OrderVO> result = ordersList.stream()
                .map(order -> {
                    OrderVO vo = new OrderVO();
                    BeanUtils.copyProperties(order, vo);
                    //使用map的getOrDefault方法进行获取如果对应键值的数据存在则进行返回，否则返回Collections.emptyList()
                    vo.setOrderDetailList(detailsMap.getOrDefault(order.getId(), Collections.emptyList()));
                    return vo;
                })
                .collect(Collectors.toList());

        return new PageResult(pageInfo.getTotal(), result);
    }

    @Override
    public OrderVO queryOrderDetail(Long id) {
        //1、根据订单的id进行查询订单的信息
        Orders orders = orderMapper.queryOrderById(id);
        //2、根据order_id进行获取订单详情对应的列表
        List<OrderDetail> orderDetailList = orderDetailMapper.queryByOrderId(id);
        //3、对获取到的数据进行封装
        OrderVO orderVO = new OrderVO();
        BeanUtils.copyProperties(orders,orderVO);
        orderVO.setOrderDetailList(orderDetailList);
        return orderVO;
    }

    @Override
    public void cancelOrder(Long id) {
        //逻辑梳理，首先根据订单id获取订单的信息，根据订单的状态决定后续的操作
        //若是待付款，用户直接取消订单，若是待接单，已接单，派送中，则进行取消订单并且将用户的钱进行退回。若是已完成，退款则不能进行取消订单，若是已取消则进行返回
        //实现1：根据订单的id获取订单的信息
        Orders orders = orderMapper.queryOrderById(id);
        //实现2：若订单不存在则直接抛出异常
        if(orders == null){
            throw new OrderBusinessException(MessageConstant.ORDER_NOT_FOUND);
        }
        //实现3:获取订单的状态
        Integer status = orders.getStatus();
        //实现4：当订单状态为5已完成，6已取消时，不进行处理直接进行返回
        if(status == Orders.COMPLETED || status == Orders.CANCELLED){
            return;
        }
        //实现5：创建更新对象
        Orders updateOrder = new Orders();
        updateOrder.setId(orders.getId());
        updateOrder.setStatus(Orders.CANCELLED);
        updateOrder.setCancelReason("用户取消");
        updateOrder.setCancelTime(LocalDateTime.now());
        try {
            //当订单的状态为1待付款时，用户可以直接取消订单
            if(status == Orders.PENDING_PAYMENT){
                orderMapper.update(updateOrder);
            }
            //当订单状态为2待接单,3已接单,4派送中时，需要线将用户的钱进行退回，然后更新订单
            else if(status == Orders.TO_BE_CONFIRMED || status == Orders.CONFIRMED || status == Orders.DELIVERY_IN_PROGRESS){
                weChatPayUtil.refund(
                        orders.getNumber(),//商户订单号
                        orders.getNumber(),//商户退单号
                        orders.getAmount(),//退款金额
                        orders.getAmount());//原订单金额
                orders.setPayStatus(Orders.REFUND);
                orderMapper.update(updateOrder);
            }
        } catch (Exception e) {
            log.error("订单取消失败，订单ID：{}", id, e);
            throw new OrderBusinessException("取消订单失败: " + e.getMessage());
        }
    }

    @Override
    public void repetitionOrder(Long id) {
        //1、根据订单号查询订单详情列表，一个订单中有多个商品，将所有的商品都重新加入购物车
        List<OrderDetail> orderDetailList = orderDetailMapper.queryByOrderId(id);
        //2、将订单详情列表中的数据封装到购物车中
        Long userId = BaseContext.getCurrentId();
        List<ShoppingCart> shoppingCartList = new ArrayList<>();
        //使用遍历循环，获取每一个实体对象然后将其加入集合中
        for (OrderDetail orderDetail : orderDetailList){
            ShoppingCart shoppingCart = new ShoppingCart();
            BeanUtils.copyProperties(orderDetail,shoppingCart,"id");
            shoppingCart.setUserId(userId);
            shoppingCart.setNumber(1);
            shoppingCart.setCreateTime(LocalDateTime.now());
            shoppingCartList.add(shoppingCart);
        }
        //也可以将上述的遍历循环使用stream流进行封装
//        List<ShoppingCart> result =orderDetailList.stream().map(orderDetail->{
//            ShoppingCart shoppingCart = new ShoppingCart();
//            BeanUtils.copyProperties(orderDetail,shoppingCart,"id");
//            shoppingCart.setUserId(userId);
//            shoppingCart.setNumber(1);
//            shoppingCart.setCreateTime(LocalDateTime.now());
//            return shoppingCart;
//        }).collect(Collectors.toList());
        //3、在购物车中插入数据
        shoppingCartMapper.insertBatch(shoppingCartList);
    }

    @Override
    public PageResult conditionSearch(OrdersPageQueryDTO ordersPageQueryDTO) {
        //1、使用PageHelper来进行分页
        PageHelper.startPage(ordersPageQueryDTO.getPage(),ordersPageQueryDTO.getPageSize());
        //2、在管理端，可以查询到所有用户的订单的信息，所以直接进行查询没必要筛选用户
        List<Orders> ordersList = orderMapper.queryListByCondition(ordersPageQueryDTO);
        //3、进行分页,将获取到的数据进行分页
        PageInfo<Orders> pageInfo = new PageInfo<>(ordersList);
        //4、创建一个新的list集合，用于填充数据
        List<OrderVO> list = new ArrayList<>();
        //5、获取分页后的订单的数据,如果使用一开始的ordersList会导致后续的结果不是分页的
        List<Orders> orderList = pageInfo.getList();
        //6、当获取到的分页数据不为空，然后遍历分页数据，根据订单id获取订单详情列表的数据
        if(!CollectionUtils.isEmpty(orderList)){
            for (Orders orders : orderList){
                OrderVO orderVO = new OrderVO();
                BeanUtils.copyProperties(orders,orderVO);
                List<OrderDetail> orderDetailList = orderDetailMapper.queryByOrderId(orders.getId());
                //将获取到的数据进行处理，将获取到的列表的数据转为字符串
                List<String> orderDishList = orderDetailList.stream().map(orderDetail->{
                    String orderDish = orderDetail.getName() + "*" + orderDetail.getNumber() + ";";
                    return orderDish;
                }).collect(Collectors.toList());
                String orderDishs = String.join("",orderDishList);
                //将数据存入orderVO中
                orderVO.setOrderDishes(orderDishs);
                list.add(orderVO);
            }
        }
        //6、返回结果
        return new PageResult(pageInfo.getTotal(),list);
    }

    @Override
    public OrderVO queryOrderById(Long id) {
        //根据订单的id进行查询订单，
        Orders orders = orderMapper.queryOrderById(id);
        //根据订单的id进行查询订单详情的数据
        List<OrderDetail> orderDetailList = orderDetailMapper.queryByOrderId(id);
        //创建一个OrderVO对象，用于封装
        OrderVO orderVO = new OrderVO();
        BeanUtils.copyProperties(orders,orderVO);
        orderVO.setOrderDetailList(orderDetailList);
        //将封装后的数据进行返回
        return orderVO;
    }

    @Override
    public void updateStatus(OrdersConfirmDTO ordersConfirmDTO) {
        //根据订单的id进行更新status状态
        orderMapper.updateOrderStatus(ordersConfirmDTO);
    }

    @Override
    public void rejectionOrder(OrdersRejectionDTO ordersRejectionDTO) {
        //根据订单的id查询订单的信息
        Orders orders = orderMapper.queryOrderById(ordersRejectionDTO.getId());
        //当订单不存在或者订单状态不是待接单的时候，直接进行抛出异常
        if (orders == null || orders.getStatus() != Orders.TO_BE_CONFIRMED) {
            throw new OrderBusinessException(MessageConstant.ORDER_STATUS_ERROR);
        }
//            //当用户的支付状态为已支付时，需要退钱
//            try {
//                if (orders.getPayStatus() == Orders.PAID) {
//                    weChatPayUtil.refund(
//                            orders.getNumber(),
//                            orders.getNumber(),
//                            orders.getAmount(),
//                            orders.getAmount());
//                }
//            } catch (Exception e) {
//                throw new RuntimeException(e);
//            }
        //创建一个新的orders对象，用于封装数据
        Orders updateOrder = new Orders();
        updateOrder.setId(orders.getId());
        updateOrder.setStatus(Orders.CANCELLED);
        updateOrder.setRejectionReason(ordersRejectionDTO.getRejectionReason());
        updateOrder.setCancelTime(LocalDateTime.now());
        //进行更新操作
        orderMapper.update(updateOrder);
    }

    @Override
    public void admincancelOrder(OrdersCancelDTO ordersCancelDTO) {
        //根据订单的id查询订单的信息
        Orders order = orderMapper.queryOrderById(ordersCancelDTO.getId());
        //获取订单的状态进行判断，若订单状态为已完成或者已取消或者未接单直接进行抛出异常，未接单直接接单或者拒单
        if(order.getStatus() == Orders.COMPLETED || order.getStatus() == Orders.CANCELLED || order.getStatus() == Orders.TO_BE_CONFIRMED){
            throw new OrderBusinessException(MessageConstant.ORDER_STATUS_ERROR);
        }
        //若订单状态为其他，则判断用户的支付状态，若用户已支付则进行退款，若用户未支付则进行订单的取消
        if(order.getPayStatus() == Orders.PAID){
            try {
                weChatPayUtil.refund(
                        order.getNumber(),
                        order.getNumber(),
                        order.getAmount(),
                        order.getAmount());
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
        //封装要更新的参数，取消订单的原因，取消订单的时间，进行更新数据库中订单的数据
        Orders updateOrder = Orders.builder()
                .id(order.getId())
                .status(Orders.CANCELLED)
                .cancelReason(ordersCancelDTO.getCancelReason())
                .cancelTime(LocalDateTime.now())
                .build();
        orderMapper.update(updateOrder);
    }

    @Override
    public void deliveryOrder(Long id) {
        //根据订单的id进行查询订单的信息
        Orders order = orderMapper.queryOrderById(id);
        //获取订单的状态进行判断，只有待派送（已接单）的订单，可以进行更改订单状态为派送中，
        if(order.getStatus() == Orders.CONFIRMED){
            Integer status = Orders.DELIVERY_IN_PROGRESS;
            Orders updateOrder = Orders.builder()
                    .status(status)
                    .id(id)
                    .build();
            orderMapper.update(updateOrder);
        }else{
            throw new OrderBusinessException(MessageConstant.ORDER_STATUS_ERROR);
        }
    }

    @Override
    public void completeOrder(Long id) {
        //根据订单的id进行查询订单的信息
        Orders order = orderMapper.queryOrderById(id);
        //获取订单的状态，只有派送中的订单才可以改为已完成状态
        if(order.getStatus() == Orders.DELIVERY_IN_PROGRESS){
            Integer status = Orders.COMPLETED;
            Orders updateOrder = Orders.builder()
                    .status(status)
                    .id(id)
                    .build();
                    orderMapper.update(updateOrder);
        }
    }

    @Override
    public void reminderOrder(Long id) {
        //根据订单id查询订单的信息，当查询到订单信息后，使用webScoket对管理端进行提醒
        Orders order = orderMapper.queryOrderById(id);
        if(order == null){
            throw new OrderBusinessException(MessageConstant.ORDER_NOT_FOUND);
        }
        //基于webSocket进行催单
        Map map = new HashMap();
        map.put("type",2);
        map.put("orderId",id);
        map.put("content","订单号：" + order.getNumber());
        webSocketServer.sendToAllClient(JSON.toJSONString(map));
    }
//    @Override
//    public PageResult queryHistoryOrders(Integer page, Integer pageSize, Integer status) {
//        //根据用户的Id，进行查找历史订单并且进行分页
//        Long userId = BaseContext.getCurrentId();
//        //创建一个传递的参数的结构，方便进行数据的传递
//        OrdersPageQueryDTO ordersPageQueryDTO = new OrdersPageQueryDTO();
//        ordersPageQueryDTO.setUserId(userId);
//        ordersPageQueryDTO.setStatus(status);
//        //使用Pagehelper进行设置分页
//        PageHelper.startPage(page,pageSize);
//        //进行执行数据库操作，返回的是一个List集合
//        List<Orders> ordersList = orderMapper.queryList(ordersPageQueryDTO);
//        PageInfo<Orders> pageInfo = new PageInfo<>(ordersList);
//        //创建一个新的list集合，用于填充数据
//        List<OrderVO> list = new ArrayList<>();
//        //遍历pageInfo集合，将数据进行封装
//        if(pageInfo.getList() != null && pageInfo.getList().size() > 0){
//            for (Orders orders : pageInfo.getList()) {
//                //创建单项的OrderVO
//                OrderVO orderVO = new OrderVO();
//                List<OrderDetail> orderDetailList = orderDetailMapper.queryByOrderId(orders.getId());
//                BeanUtils.copyProperties(orders,orderVO);
//                orderVO.setOrderDetailList(orderDetailList);
//                list.add(orderVO);
//            }
//        }
//        return new PageResult(pageInfo.getTotal(),list);
//    }


}
